package com.szeldon.declatest.exec;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import org.testng.Assert;
import org.testng.annotations.Test;

import com.szeldon.declatest.declaration.TestsSuiteDeclaration;
import com.szeldon.declatest.declaration.reader.XMLDeclarationReader;
import com.szeldon.declatest.declaration.reader.exceptions.TestSuiteFileException;
import com.szeldon.declatest.declaration.reader.settings.JMSSettingsReaderPlugin;
import com.szeldon.declatest.declaration.scenario.parts.EndPartDeclaration;
import com.szeldon.declatest.declaration.scenario.parts.ErrorPartDeclaration;
import com.szeldon.declatest.declaration.scenario.parts.NotComputedPartDeclaration;
import com.szeldon.declatest.eval.IScenarioEvaluatorPlugin;
import com.szeldon.declatest.eval.plugins.DefaultEvaluatorPlugin;
import com.szeldon.declatest.exec.events.ElseConditionEvaluationEndExecEvent;
import com.szeldon.declatest.exec.events.ElseConditionEvaluationStartExecEvent;
import com.szeldon.declatest.exec.events.IfConditionEvaluationEndExecEvent;
import com.szeldon.declatest.exec.events.IfConditionEvaluationStartExecEvent;
import com.szeldon.declatest.exec.events.ScenarioExecutionEndExecEvent;
import com.szeldon.declatest.exec.events.ScenarioExecutionStartExecEvent;
import com.szeldon.declatest.exec.plugins.JMSDoScenarioPartExecutorPlugin;
import com.szeldon.declatest.exec.result.EndScenarioExecutionResult;
import com.szeldon.declatest.exec.result.ErrorScenarioExecutionResult;
import com.szeldon.declatest.exec.result.NotComputedScenarioExecutionResult;

/**
 * Tests for {@link SingleThreadExecutor} class. This class contains only tests of logical part of execution (If, Else,
 * Return, End, Checkpoint, Error, NotComputed). Execution of DoScenarioParts is tested in separate classes.
 * 
 * @author szeldon
 * 
 */
public class SingleThreadExecutorTest {

    private static final String TEST_DECLARATION_DIRECTORY = "tests-res/com/szeldon/declatest";

    @Test
    public void testProperSuite() throws FileNotFoundException, IOException, TestSuiteFileException {

        final String scenarioId = "scenario-00";

        XMLDeclarationReader reader = new XMLDeclarationReader(TEST_DECLARATION_DIRECTORY + "/exec/proper-suite-01.xml");
        reader.addSettingsReaderPlugin(new JMSSettingsReaderPlugin());

        // test suite
        TestsSuiteDeclaration suite = reader.readTestsSuiteDeclaration();

        SingleThreadExecutor executor = new SingleThreadExecutor();
        executor.addTestsSuiteDeclaration(suite);
        executor.addEvaluatorPlugin(new DefaultEvaluatorPlugin());
        executor.addDoScenarioPartExecutorPlugin(new JMSDoScenarioPartExecutorPlugin());

        ExecListenerTester listener = new ExecListenerTester();
        listener.addEventToCompare(new ScenarioExecutionStartExecEvent(scenarioId, null, null));
        listener.addEventToCompare(new IfConditionEvaluationStartExecEvent(scenarioId, null, null, "1", "equals", "1",
                "some description"));
        listener.addEventToCompare(new IfConditionEvaluationEndExecEvent(scenarioId, null, null, "1", "equals", "1",
                "some description", true));
        listener.addEventToCompare(new IfConditionEvaluationStartExecEvent(scenarioId, null, null, "left", "equals",
                "left", "some other description"));
        listener.addEventToCompare(new IfConditionEvaluationEndExecEvent(scenarioId, null, null, "left", "equals",
                "left", "some other description", true));
        NotComputedScenarioExecutionResult result = new NotComputedScenarioExecutionResult(
                new NotComputedPartDeclaration("description, oh yeah"));
        listener.addEventToCompare(new ScenarioExecutionEndExecEvent(scenarioId, null, null, result));

        executor.setListener(listener);
        executor.execute();

        Assert.assertEquals(listener.isExecutionOk(), true, listener.notOkExecutionDescription());

    }

    @Test
    public void testProperSuite2() throws FileNotFoundException, IOException, TestSuiteFileException {
        final String scenarioId = "scenario-00";

        XMLDeclarationReader reader = new XMLDeclarationReader(TEST_DECLARATION_DIRECTORY + "/exec/proper-suite-02.xml");
        reader.addSettingsReaderPlugin(new JMSSettingsReaderPlugin());

        // test suite
        TestsSuiteDeclaration suite = reader.readTestsSuiteDeclaration();

        SingleThreadExecutor executor = new SingleThreadExecutor();
        executor.addTestsSuiteDeclaration(suite);
        executor.addEvaluatorPlugin(new DefaultEvaluatorPlugin());

        EndScenarioExecutionResult result = new EndScenarioExecutionResult(new EndPartDeclaration(
                "some other end description"));

        ExecListenerTester listener = new ExecListenerTester();
        listener.addEventToCompare(new ScenarioExecutionStartExecEvent(scenarioId, null, null));
        listener.addEventToCompare(new IfConditionEvaluationStartExecEvent(scenarioId, null, null, "1", "equals", "2",
                "some description"));
        listener.addEventToCompare(new IfConditionEvaluationEndExecEvent(scenarioId, null, null, "1", "equals", "2",
                "some description", false));
        listener.addEventToCompare(new ElseConditionEvaluationStartExecEvent(scenarioId, null, null, "2", "equals",
                "2", "some description"));
        listener.addEventToCompare(new ElseConditionEvaluationEndExecEvent(scenarioId, null, null, "2", "equals", "2",
                "some description", true));
        listener.addEventToCompare(new ScenarioExecutionEndExecEvent(scenarioId, null, null, result));

        executor.setListener(listener);
        executor.execute();

        Assert.assertEquals(listener.isExecutionOk(), true, listener.notOkExecutionDescription());
    }

    @Test
    public void testProperSuite3() throws FileNotFoundException, IOException, TestSuiteFileException {
        final String scenarioId = "scenario-00";

        XMLDeclarationReader reader = new XMLDeclarationReader(TEST_DECLARATION_DIRECTORY + "/exec/proper-suite-03.xml");
        reader.addSettingsReaderPlugin(new JMSSettingsReaderPlugin());

        // test suite
        TestsSuiteDeclaration suite = reader.readTestsSuiteDeclaration();

        SingleThreadExecutor executor = new SingleThreadExecutor();
        executor.addTestsSuiteDeclaration(suite);
        executor.addEvaluatorPlugin(new DefaultEvaluatorPlugin());

        ErrorScenarioExecutionResult result = new ErrorScenarioExecutionResult(new ErrorPartDeclaration(
                "some other end description"));

        ExecListenerTester listener = new ExecListenerTester();
        listener.addEventToCompare(new ScenarioExecutionStartExecEvent(scenarioId, null, null));
        listener.addEventToCompare(new IfConditionEvaluationStartExecEvent(scenarioId, null, null, "1", "equals", "2",
                "some description"));
        listener.addEventToCompare(new IfConditionEvaluationEndExecEvent(scenarioId, null, null, "1", "equals", "2",
                "some description", false));
        listener.addEventToCompare(new ElseConditionEvaluationStartExecEvent(scenarioId, null, null, "foo", "equals",
                "bar", "some description"));
        listener.addEventToCompare(new ElseConditionEvaluationEndExecEvent(scenarioId, null, null, "foo", "equals",
                "bar", "some description", false));
        listener.addEventToCompare(new ElseConditionEvaluationStartExecEvent(scenarioId, null, null, "foo",
                "notEquals", "bar", "ohoh"));
        listener.addEventToCompare(new ElseConditionEvaluationEndExecEvent(scenarioId, null, null, "foo", "notEquals",
                "bar", "ohoh", true));
        listener.addEventToCompare(new ScenarioExecutionEndExecEvent(scenarioId, null, null, result));

        executor.setListener(listener);
        executor.execute();

        Assert.assertEquals(listener.isExecutionOk(), true, listener.notOkExecutionDescription());
    }

    @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Plugin name can't contain.*")
    public void testNotProperPlugin() throws FileNotFoundException, IOException, TestSuiteFileException {

        XMLDeclarationReader reader = new XMLDeclarationReader(TEST_DECLARATION_DIRECTORY + "/exec/proper-suite-01.xml");
        reader.addSettingsReaderPlugin(new JMSSettingsReaderPlugin());

        // test suite
        TestsSuiteDeclaration suite = reader.readTestsSuiteDeclaration();

        SingleThreadExecutor executor = new SingleThreadExecutor();
        executor.addTestsSuiteDeclaration(suite);
        executor.addEvaluatorPlugin(new IScenarioEvaluatorPlugin() {
            @Override
            public String getPluginPrefix() {
                return "not#properpluginname";
            }

            @Override
            public boolean evaluateOperator(AbstractTestsSuiteExecutor executor, String leftValue, String operator,
                    String rightValue, Properties properties, TestSuiteExecHistory history) {
                // TODO Auto-generated method stub
                throw new UnsupportedOperationException("Not YET implemented.");
            }

            @Override
            public String evaluateValue(AbstractTestsSuiteExecutor executor, String value, Properties properties,
                    TestSuiteExecHistory history) {
                // TODO Auto-generated method stub
                throw new UnsupportedOperationException("Not YET implemented.");
            }

        });
        executor.execute();

    }
}
